package Controler;

import java.awt.Point;
import java.util.Observable;
import java.util.Observer;

import Data.GameStatus;
import Data.Move;
import Data.Name;
import Model.Color;
import Model.Game;
import Model.GameType;
import Model.PropertiesUtils;
import Network.Client;
import Network.Server;
import View.Checkerboard;
import View.Window;

public class Controler {
	private Game game;
	private Window window;
	private CheckerboardListener listener;
	private ConnectToServerListener ctsl;
	private LaunchServerListener lsl;
	private LaunchGameListener lgl;
	private InformationsListener il;
	private Server server;
	private Client client;
	
	public Controler(Game game, Window window){
		this.game = game;
		this.window = window;
		listener = new CheckerboardListener(this);
		lsl = new LaunchServerListener(this);
		ctsl = new ConnectToServerListener(this);
		lgl = new LaunchGameListener(this);
		il = new InformationsListener(this);
		window.addListener(listener, lsl, ctsl, lgl, il);
		game.addObserver(window);
	}
	
	public boolean movePiece(Point source, Point dest){
		if(game.getGameType() == GameType.Local)
		{
			if(game.movePiece(source, dest)){
				game.getGameStatus().setNextPlayer((game.getGameStatus().getNextPlayer()+1)%2);	
				if(game.getGameStatus().isFinish()){
					window.removeListener(listener,il);
				}
				return true;
			}else{
				this.selected(dest);
			}
		}
		else if(game.getGameType() == GameType.Server && game.getGameStatus().getNextPlayer() == 0)
		{
			if(game.getPieceColor(source) != null)
			{
				if(game.getPieceColor(source) == Color.White)
					if(game.movePiece(source, dest))
					{
						game.getGameStatus().setNextPlayer((game.getGameStatus().getNextPlayer()+1)%2);
						if(game.getGameStatus().getNextPlayer() != game.getLocalPlayer() && !game.getGameStatus().isFinish()){
							changeMessage(PropertiesUtils.informationsProperties("opponentPlay") );
						}
						if(server != null)
						{
							server.send(new Move(source, dest));
							server.send(game.getGameStatus());
						}
						if(game.getGameStatus().isFinish()){
							window.removeListener(listener,il);
						}
						return true;
					}else{
						game.analyzePoint(dest);
					}
					
			}
		}
		else if(game.getGameType() == GameType.Client && game.getGameStatus().getNextPlayer() == 1)
		{
			if(game.getPieceColor(source) != null)
			{
				if(game.getPieceColor(source) == Color.Black )
					if(game.movePiece(source, dest))
					{
						game.getGameStatus().setNextPlayer((game.getGameStatus().getNextPlayer()+1)%2);
						if(game.getGameStatus().getNextPlayer() != game.getLocalPlayer() && !game.getGameStatus().isFinish()){
							changeMessage(PropertiesUtils.informationsProperties("opponentPlay"));
						}
						if(client != null)
						{
							client.send(new Move(source, dest));
							client.send(game.getGameStatus());
						}
						if(game.getGameStatus().isFinish()){
							window.removeListener(listener,il);
						}
						return true;
					}else{
						game.analyzePoint(dest);
					}
			}
		}
		return false;
	}
	
	public void sendPossibleMoves(Point p)
	{
		game.notifyObserversPossibleMoves(p);
		changeMessage(PropertiesUtils.informationsProperties("sendPossibleMoves"));
	}
	
	public void launchServer(int port){
		server = new Server(this, port);
		this.game.setGameType(GameType.Server);
		Thread s = new Thread(server);
		s.start();
	}
	
	public void connectToServer(String ip, int port){
		client = new Client(this, ip, port);
		this.game.setGameType(GameType.Client);
		Thread c = new Thread(server);
		c.start();
	}
	
	public void changeMessage(String message){
		window.setInformations(message);
	}
	
	public void receive(Object obj)
	{
		if(obj instanceof Move && !game.getGameStatus().isFinish())
		{
			if(game.getPieceColor(((Move)obj).getStart()) == Color.White && game.getLocalPlayer() == 1
					|| game.getPieceColor(((Move)obj).getStart()) == Color.Black && game.getLocalPlayer() == 0)
			{
				game.movePiece(((Move)obj).getStart(), ((Move)obj).getEnd());
				changeMessage(PropertiesUtils.informationsProperties("youPlay"));
			}
		}
		else if(obj instanceof GameStatus)
		{
			this.game.updateGameStatus((GameStatus)obj);
			GameStatus gameStatus = (GameStatus)obj;
			if(gameStatus.isFinish()){
				window.removeListener(listener,il);
				window.setInformations(PropertiesUtils.informationsProperties("echec") + "\n" + PropertiesUtils.informationsProperties("loose"));
			}			
			this.setScore(Integer.parseInt(PropertiesUtils.informationsProperties("player1"))
					,gameStatus.getScore(Integer.parseInt(PropertiesUtils.informationsProperties("player1"))));
			this.setScore(Integer.parseInt(PropertiesUtils.informationsProperties("player2"))
					,gameStatus.getScore(Integer.parseInt(PropertiesUtils.informationsProperties("player2"))));
		}			
		else if(obj instanceof Name)
		{
			Name n = (Name)obj;
			this.setPlayerName(n.getPlayer(), n.getName());
		}
	}
	
	public void hostReceivedClient()
	{
		game.launch(0);
		window.displayLocalPlayer(0);
		changeMessage(PropertiesUtils.informationsProperties("youPlay"));
		server.send(game.getGameStatus());
	}
	
	public void connectedToHost()
	{
		changeMessage(PropertiesUtils.informationsProperties("opponentPlay"));
		game.launch(1);
		window.displayLocalPlayer(1);
	}
	
	public void launchGame(){
		this.game.setGameType(GameType.Local);
		game.launch(0);
		window.displayLocalPlayer(0);
	}
	
	public void setPlayerName(int player, String name){
		window.setPlayerName(player, name);
	}
	
	public void setScore(int player, int score){
		window.setScore(player, score);
	}
	
	public void send(Object obj){
		if(server != null){
			server.send(obj);
		}else if(client != null){
			client.send(obj);
		}
	}
	
	public boolean selected(Point p){
		return game.analyzePoint(p);
	}
	
	
}
